using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.IO;

namespace Neeko.XNA.UI
{
    public delegate void ButtonEvent(Button sender);

    public class Button
    {
        public Vector2 Position { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }

        public String Text { get; set; }

        public bool IsMouseOver { get; private set; }
        public bool IsPressed { get; private set; }

        //TODO: izmakni u IKeyboardListener
        public bool IsSelected { get; set; }

        //left button events
        public event ButtonEvent OnClick;
        public event ButtonEvent OnMousePress;
        public event ButtonEvent OnMouseRelease;

        public event ButtonEvent OnMouseEnter;
        public event ButtonEvent OnMouseLeave;

        MouseState _previousState;

        int _textureWidth;
        int _textureHeight;
        int _spriteHeight;
        const int NumberOfSprites = 4;

        public Button(Vector2 position, String text)
        {
            this.Position = position;
            _previousState = Mouse.GetState();

            Texture2D texture = UIResourceRepository.Resolve(typeof(Button));
            this.Width = texture.Width;
            this.Height = texture.Height / NumberOfSprites;

            _textureWidth = texture.Width;
            _textureHeight = texture.Height;
            _spriteHeight = this.Height;

            this.Text = text;
        }

        /// <summary>
        /// Instanciates a Button. Default dimensions: 86*24;
        /// </summary>
        public Button() : this(Vector2.Zero, "Button") { }

        /// <summary>
        /// Instanciates a Button. Default dimensions: 86*24;
        /// </summary>
        public Button(String text) : this(Vector2.Zero, text) { }

        public void Update(GameTime gameTime)
        {
            MouseState mouseState = Mouse.GetState();

            Rectangle buttonRect = new Rectangle((int)this.Position.X, (int)this.Position.Y, this.Width, this.Height);
            Point mousePoint = new Point(mouseState.X, mouseState.Y);
            Point previousPoint = new Point(_previousState.X, _previousState.Y);

            if (buttonRect.Contains(mousePoint))
            {
                this.IsMouseOver = true;
                if (!buttonRect.Contains(previousPoint))
                    if (OnMouseEnter != null)
                        OnMouseEnter(this);

                //left button was pressed
                if (_previousState.LeftButton == ButtonState.Released && mouseState.LeftButton == ButtonState.Pressed)
                {
                    if (OnMousePress != null)
                        OnMousePress(this);

                    this.IsPressed = true;
                }

                //left button was released
                if (_previousState.LeftButton == ButtonState.Pressed && mouseState.LeftButton == ButtonState.Released)
                {
                    if (OnMouseRelease != null)
                        OnMouseRelease(this);

                    if (this.IsPressed && OnClick != null)
                        OnClick(this);

                    this.IsPressed = false;
                }
            }
            else
            {
                if (mouseState.LeftButton == ButtonState.Released)
                    this.IsPressed = false;

                this.IsMouseOver = false;

                if (buttonRect.Contains(previousPoint))
                {
                    if (OnMouseLeave != null)
                        OnMouseLeave(this);
                }
            }

            _previousState = mouseState;
        }

        /// <summary>
        /// Draws this Button
        /// SpriteBatch.Begin() should already be called, with BlendState.NonPremultiplied
        /// </summary>
        /// <param name="spriteBatch">SpriteBatch used to draw this component</param>
        public void Draw(SpriteBatch spriteBatch)
        {
            Rectangle sourceRectangle = new Rectangle(0, IsMouseOver ? (IsPressed ? _spriteHeight * 2 : _spriteHeight) : 0, _textureWidth, _spriteHeight);
            Rectangle destinationRectangle = new Rectangle((int)this.Position.X, (int)this.Position.Y, this.Width, this.Height);

            spriteBatch.Draw(UIResourceRepository.Resolve(typeof(Button)), destinationRectangle, sourceRectangle, Color.White);

            SpriteFont font = UIResourceRepository.UIFont;
            Vector2 textSize = font.MeasureString(this.Text);

            //setting up font to look sharp
            Vector2 relativeTextPosition = new Vector2((float)(this.Width / 2.0 - textSize.X / 2.0), (float)(this.Height / 2.0 - textSize.Y / 2.0));
            Vector2 textPosition = this.Position + relativeTextPosition;
            Vector2 realTextPosition = new Vector2((int)textPosition.X, (int)textPosition.Y);

            spriteBatch.DrawString(font, this.Text, realTextPosition, Color.Black);
        }
    }
}
